Skip to content

feat: async client + async tool variants (AsyncRustChainClient) — #1 Task 2 - #3

Merged
Scottcjn merged 7 commits into
Scottcjn:mainfrom
Vyacheslav-Tomashevskiy:feat-async-client
Jul 4, 2026
Merged

feat: async client + async tool variants (AsyncRustChainClient) — #1 Task 2#3
Scottcjn merged 7 commits into
Scottcjn:mainfrom
Vyacheslav-Tomashevskiy:feat-async-client

Conversation

@Vyacheslav-Tomashevskiy

Copy link
Copy Markdown
Contributor

Implements Task 2 — Async client (8 RTC) from #1.

Adds an async (httpx) twin of the read-only client plus matching async tools, so an agent can fan out several RustChain reads concurrently instead of blocking on each request.

What's added

  • AsyncRustChainClient (rustchain_langchain/async_client.py) — mirrors RustChainClient method-for-method (network_stats, payouts, metrics, miners, health, balance, epoch, bounties), every call a coroutine backed by httpx.AsyncClient. Returns the exact same shapes, so the existing framework-free summarize_* helpers consume its output unchanged.
  • get_async_rustchain_tools() — the same 7 LangChain tools (same names, descriptions and args_schema for rustchain_balance/rustchain_bounties), but each tool's _arun awaits the async client. _run bridges to the coroutine for sync callers when no event loop is already running.
  • Both exported from the package root.

Safety contract kept

  • Read-only / keyless — same public endpoints as the sync client, no writes, no secrets.
  • Tools never raise inside an agent loop — failures are wrapped and returned as a string.
  • httpx is imported lazily in the request path, so the sync client and summarize_* helpers keep working without it installed. Added as an optional async extra (and to test).

Tests

pytest -q23 passed (10 new). HTTP is fully mocked (httpx.AsyncClient monkeypatched), coroutines driven with asyncio.run — no network, no pytest-asyncio needed. New tests cover URL/param building, the balance miner_id pass-through, the bounties reshape, concurrent asyncio.gather fan-out, async tool _arun success + never-raise, the sync bridge, and sync/async tool-name parity.

Live-smoke-tested against rustchain.org too: 3 concurrent reads in ~0.5s, all summaries correct.

/claim #1

@jaxint jaxint left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

感谢您的贡献!代码审查完成。

钱包地址: AhqbFaPBPLMMiaLDzA9WhQcyvv4hMxiteLhPk3NhG1iG

Automated review by RustChain bounty participant.

@jaxint jaxint left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PR Review Summary

Thank you for this contribution to the RustChain ecosystem!

Quick Review

  • ✅ PR title is clear and descriptive
  • ✅ Changes align with project goals
  • ✅ Appreciate the effort in improving the codebase

Wallet for RTC Reward

AhqbFaPBPLMMiaLDzA9WhQcyvv4hMxiteLhPk3NhG1iG


Automated review by RustChain bounty hunter

@Scottcjn

Copy link
Copy Markdown
Owner

Consolidated change-request for this stack is on #2 (#2 (comment)) — it covers the async-extra packaging, bounty-shape consistency, and reward parsing across #2/#3/#4. Addressing those there unblocks all three. Thanks!

Vyacheslav-Tomashevskiy and others added 7 commits June 21, 2026 02:44
This file implements an asynchronous read-only HTTP client for RustChain's public API using httpx. It provides methods to access various endpoints like network stats, payouts, miners, and bounties, allowing concurrent requests.
Added asynchronous RustChain tools for balance and bounties.
Added AsyncRustChainClient and related async tools to the module.
Added section on async client for concurrent reads with examples.
Added tests for AsyncRustChainClient methods and tools.
…ps, safer parser

Addresses the consolidated Codex+Grok review on Scottcjn#2 (blocks Scottcjn#2 -> Scottcjn#3 -> Scottcjn#4):

1. (blocking) Documented async install path now self-sufficient: the `async`
   extra pulls langchain-core too, so `pip install "...[async]"` then
   `get_async_rustchain_tools()` works without also installing `[langchain]`.
   README updated to match.
2. (blocking) One canonical bounty contract shared by sync + async: new
   `_bounties_search_url` / `_reshape_bounty` / `_parse_reward` in client.py;
   both `RustChainClient.bounties` and `AsyncRustChainClient.bounties` funnel
   through them, so output is byte-for-byte identical (new parity test).
3. (should-fix) Reward parser no longer misreports: query filters `label:bounty`,
   amount is read from title *and* body, and decimals are preserved
   (`[BOUNTY: 50 RTC]`, `2.5 RTC`) instead of falling back to "see issue".
4. (should-fix) Test skip-guards narrowed from broad `except Exception` to
   `(ImportError, ModuleNotFoundError)` so real failures aren't silently passed.
5. Confirmed `__all__` still exports AsyncRustChainClient / get_async_rustchain_tools.

All 25 tests pass.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@Vyacheslav-Tomashevskiy

Copy link
Copy Markdown
Contributor Author

Thanks for the detailed consolidated review @Scottcjn — that was very clear. I pushed a commit to this branch (#3) that addresses the stack-wide blockers; since they centre on the async packaging + bounty contract, fixing them here is the right home and #4 will rebase cleanly on top.

Blocking

  1. Async install path now self-sufficient — the async extra pulls langchain-core in addition to httpx, so the documented pip install "...[async]"get_async_rustchain_tools() works on its own (no need to also install [langchain]). README install line updated to say so.
  2. One canonical bounty contract — added _bounties_search_url / _reshape_bounty / _parse_reward in client.py; both RustChainClient.bounties and AsyncRustChainClient.bounties now funnel through them, so sync and async return byte-for-byte identical output. New test test_sync_and_async_bounties_share_canonical_shape asserts exactly that on the same raw issue.

Should-fix
3. Reward parser fixed — query now filters label:bounty, the amount is read from the title and body, and decimals are preserved. [BOUNTY: 50 RTC] and 2.5 RTC are captured instead of falling back to see issue (covered by test_canonical_reward_parser_reads_title_and_decimals).
4. Test guards narrowed — the langchain-optional skip guards now catch (ImportError, ModuleNotFoundError) instead of broad Exception, so a real failure surfaces instead of silently passing.
5. Confirmed __all__ still exports AsyncRustChainClient / get_async_rustchain_tools.

All 25 tests pass locally. Re #5-vs-#6 demo: agreed, keep #5 (the create_react_agent version). Happy to adjust anything else — and I'll rebase #4 on top once this lands so the export + bounty-shape carry through. Thanks again!

@Scottcjn
Scottcjn merged commit e1fc936 into Scottcjn:main Jul 4, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants